/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>
#include <internal/bus/bus_i2c/i2c.h>
#include <internal/hasdef.h>
#include <mc/dict.h>

namespace {

class bus_i2c_test : public ::testing::Test {
protected:
    dev::bus_i2c m_bus;

    void SetUp() override {
    }

    void TearDown() override {
    }
};

// 测试构造函数
TEST_F(bus_i2c_test, constructor) {
    dev::bus_i2c bus = dev::bus_i2c();
}

// 测试 init 成功
TEST_F(bus_i2c_test, init_success) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    csr_object["Speed"] = static_cast<uint32_t>(0);  // 100K
    csr_object["Mode"] = static_cast<uint8_t>(0);
}

// 测试 init 部分字段
TEST_F(bus_i2c_test, init_partial_fields) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(2);

    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), 2);
}

// 测试 init 空字典
TEST_F(bus_i2c_test, init_empty_dict) {
    mc::mutable_dict csr_object;
    EXPECT_TRUE(m_bus.init(csr_object));
}

// 测试 get_i2c_speed 有效值
TEST_F(bus_i2c_test, get_i2c_speed_valid) {
    mc::mutable_dict csr_object = {{"Id", static_cast<uint8_t>(1)}, {"Speed", static_cast<uint32_t>(0)}, {"Mode", static_cast<uint8_t>(0)}, {"SlaveAddr", static_cast<uint8_t>(0x70)}, {"UseSmbus", false}};
    EXPECT_TRUE(m_bus.init(csr_object));

    csr_object["Speed"] = static_cast<uint32_t>(2);  // 3400K
    EXPECT_TRUE(m_bus.init(csr_object));
}

// 测试 get_i2c_speed 超出范围
TEST_F(bus_i2c_test, get_i2c_speed_out_of_range) {
    mc::mutable_dict csr_object;
    csr_object["Speed"] = static_cast<uint32_t>(10);  // 超出范围，应返回原值
    EXPECT_TRUE(m_bus.init(csr_object));
}

// 测试 get_id
TEST_F(bus_i2c_test, get_id) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(5);
    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), 5);
}

// 测试 bus_lock 和 bus_unlock
TEST_F(bus_i2c_test, bus_lock_unlock) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    EXPECT_NO_THROW(m_bus.bus_lock());
    EXPECT_NO_THROW(m_bus.bus_unlock());
}

// 测试 format_tx_buf offset_width 超出范围
TEST_F(bus_i2c_test, format_tx_buf_invalid_offset_width) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    ACCESS_DATA_S data{};
    data.offset_width = 5;  // 超出最大范围4
    data.addr         = 0x70;
    data.offset       = 0x100;
    data.length       = 4;

    EXPECT_THROW(m_bus.format_tx_buf(data), mc::invalid_arg_exception);
}

// 测试 format_tx_buf 正常情况
TEST_F(bus_i2c_test, format_tx_buf_normal) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    ACCESS_DATA_S data{};
    data.offset_width = 2;
    data.addr         = 0x70;
    data.offset       = 0x1234;
    data.length       = 4;
    data.in_buffer    = {0x01, 0x02, 0x03, 0x04};

    auto tx_buf = m_bus.format_tx_buf(data);
    EXPECT_GT(tx_buf.length(), 0);
    EXPECT_EQ(tx_buf[0], 0x70);  // 地址字节
}

// 测试 normal_read 成功
TEST_F(bus_i2c_test, normal_read_success) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    ACCESS_DATA_S data{};
    data.offset_width = 1;
    data.addr         = 0x70;
    data.offset       = 0x10;
    data.length       = 4;
    data.read_time_out = 100;

    // 由于使用打桩驱动，读取应该成功
    uint32_t ret = m_bus.normal_read(data);
    EXPECT_EQ(ret, HAS_OK);
}

// 测试 extend_read 成功
TEST_F(bus_i2c_test, extend_read_success) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    ACCESS_DATA_S data{};
    data.addr         = 0x70;
    data.offset       = 0xFFFFFFFF;  // I2C_EXTEND_READ_MODE
    data.length       = 4;
    data.in_buffer    = {0x01, 0x02};
    data.read_time_out = 100;

    uint32_t ret = m_bus.extend_read(data);
    EXPECT_EQ(ret, HAS_OK);
}

// 测试 read 使用 normal_read
TEST_F(bus_i2c_test, read_normal_mode) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    ACCESS_DATA_S data{};
    data.offset_width = 1;
    data.addr         = 0x70;
    data.offset       = 0x10;
    data.length       = 4;

    uint32_t ret = m_bus.read(data);
    EXPECT_EQ(ret, HAS_OK);
}

// 测试 read 使用 extend_read
TEST_F(bus_i2c_test, read_extend_mode) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    ACCESS_DATA_S data{};
    data.addr         = 0x70;
    data.offset       = 0xFFFFFFFF;  // I2C_EXTEND_READ_MODE
    data.length       = 4;
    data.in_buffer    = {0x01, 0x02};

    uint32_t ret = m_bus.read(data);
    EXPECT_EQ(ret, HAS_OK);
}

// 测试 write 成功
TEST_F(bus_i2c_test, write_success) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    ACCESS_DATA_S data{};
    data.offset_width = 1;
    data.addr         = 0x70;
    data.offset       = 0x10;
    data.length       = 4;
    data.in_buffer    = {0x01, 0x02, 0x03, 0x04};

    uint32_t ret = m_bus.write(data);
    EXPECT_EQ(ret, HAS_OK);
}

// 测试 write 长度超出限制
TEST_F(bus_i2c_test, write_length_too_long) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    ACCESS_DATA_S data{};
    data.offset_width = 1;
    data.addr         = 0x70;
    data.offset       = 0x10;
    data.length       = 1101;  // 超出 MAX_WRITE_LEN (1100)
    data.in_buffer.resize(1101);

    EXPECT_THROW(m_bus.write(data), mc::invalid_arg_exception);
}

// 测试 init 异常处理
TEST_F(bus_i2c_test, init_exception) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = std::string("invalid");  // 无效类型

    // 应该捕获异常并返回 false
    EXPECT_FALSE(m_bus.init(csr_object));
}

// 测试多次 init
TEST_F(bus_i2c_test, init_multiple_times) {
    mc::mutable_dict csr_object1;
    csr_object1["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object1));
    EXPECT_EQ(m_bus.get_id(), 1);

    mc::mutable_dict csr_object2;
    csr_object2["Id"] = static_cast<uint8_t>(2);
    EXPECT_TRUE(m_bus.init(csr_object2));
    EXPECT_EQ(m_bus.get_id(), 2);
}

// 测试不同 offset_width 的 format_tx_buf
TEST_F(bus_i2c_test, format_tx_buf_different_offset_widths) {
    mc::mutable_dict csr_object;
    csr_object["Id"] = static_cast<uint8_t>(1);
    EXPECT_TRUE(m_bus.init(csr_object));

    for (uint8_t offset_width = 0; offset_width <= 4; ++offset_width) {
        ACCESS_DATA_S data{};
        data.offset_width = offset_width;
        data.addr         = 0x70;
        data.offset       = 0x12345678;
        data.length       = 4;
        data.in_buffer    = {0x01, 0x02, 0x03, 0x04};

        auto tx_buf = m_bus.format_tx_buf(data);
        EXPECT_GT(tx_buf.length(), 0);
        EXPECT_EQ(tx_buf[0], 0x70);  // 地址字节
    }
}

} // namespace

